// Copyright (c) Microsoft Corporation. All rights reserved.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;

namespace Microsoft.TeamFoundation.Migration.Toolkit.Wit
{
    /// <summary>
    /// Attributes for comparing file attachments.
    /// </summary>
    [Flags]
    public enum AttachmentComparisonAttributes
    {
        CreateTime = 0x01,                                  // Creation time
        LastWriteTime = 0x02,                               // Last write time
            
        All = CreateTime | LastWriteTime,                   // All known options
        None = 0,                                           // No flags
    }

    /// <summary>
    /// File attchment analyzer; used to detect conflicts in file attachments collections.
    /// </summary>
    class FileAttachmentAnalyzer : WorkItemAssociation<IMigrationFileAttachment>
    {
        private AttachmentComparisonAttributes m_flags;     // Comparison flags

        /// <summary>
        /// Creates and initializes the file attachment analyzer.
        /// </summary>
        /// <param name="flags">Comparison flags</param>
        /// <param name="attachments">Attachments to analyze</param>
        /// <returns>Analyzer object</returns>
        public static FileAttachmentAnalyzer Create(
            AttachmentComparisonAttributes flags,
            Pair<List<IMigrationFileAttachment>> attachments)
        {
            FileAttachmentAnalyzer analyzer = new FileAttachmentAnalyzer(flags);
            analyzer.Process(attachments);
            return analyzer;
        }

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="flags">Extra comparison attributes</param>
        internal FileAttachmentAnalyzer(
            AttachmentComparisonAttributes flags)
        {
            m_flags = flags;
        }

        #region Comparison static method

        /// <summary>
        /// Compares two attachments.
        /// </summary>
        /// <param name="a1">Attachment 1</param>
        /// <param name="a2">Attachment 2</param>
        /// <returns></returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods")]
        public override int Compare(
            IMigrationFileAttachment a1,
            IMigrationFileAttachment a2)
        {
            Debug.Assert(a1 != null && a2 != null, "Null attachment!");

            // Size
            int res = a1.Length.CompareTo(a2.Length);

            if (res == 0 && (m_flags & AttachmentComparisonAttributes.CreateTime) != 0)
            {
                res = CompareTimes(a1.UtcCreationDate, a2.UtcCreationDate);
            }
            if (res == 0 && (m_flags & AttachmentComparisonAttributes.LastWriteTime) != 0)
            {
                res = CompareTimes(a1.UtcLastWriteDate, a2.UtcLastWriteDate);
            }
            if (res == 0)
            {
                res = string.Compare(a1.Name, a2.Name, true, CultureInfo.InvariantCulture);
            }
            return res;
        }

        /// <summary>
        /// Compares two times with 1 second precision.
        /// </summary>
        /// <param name="t1">Time 1</param>
        /// <param name="t2">Time 2</param>
        /// <returns>-1, 0, 1</returns>
        private static int CompareTimes(
            DateTime t1,
            DateTime t2)
        {
            TimeSpan ts = t1 - t2;
            return Math.Abs(ts.TotalSeconds) < 1 ? 0 : Math.Sign(ts.TotalSeconds);
        }


        #endregion
    }
}
